A storage system can have a memory that is organized into blocks. Over time, data written in a block can be invalidated (e.g., because of host data deletion and/or data transfers internal to the storage system). Garbage collection is a process that collects the valid parts of used memory blocks (ignoring the invalidated parts) and moves them to a new block. When a block is fully invalidated, it is returned to the free block pool. Garbage collection can be controlled by keeping a “valid counter” for each block to track the number of valid flash management units in the block and/or by a program/erase cycle counter to monitor the block's endurance. A garbage collection algorithm can choose which block should be “collected” next by checking which block has the lowest “valid counter,” the highest program/erase cycle counter, and/or a program/erase cycle counter that is below average.